using System;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security;


//using ipp;

namespace AssetCapture
{
    public class ImageIngestion
    {
        public delegate void disPlayError(string message);
        public delegate void downQuality(int Index);

        ImageCodecInfo ici; 
        //IppiSize m_roi = new IppiSize(2048, 1080);
        int m_JPEGSize = 6635520;
        //JSS m_sampling = JSS.JS_411;
        //JCOLOR m_in_color = JCOLOR.JC_BGR;
        //JCOLOR m_out_color = JCOLOR.JC_YCBCR;
        bool errorOccurred = false;

        /// <summary>
        /// Divide the Image to the required number of slices
        /// </summary>
        /// <param name="totalSlice"></param>
        /// <param name="sliceIndex"></param>
        /// <param name="sourceImg"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public Image DivideImage(int totalSlice, int sliceIndex, Image sourceImg, int x, int y)
        {
            Graphics oGraphic;
            
            int sourceStartWidth;
            int sourceStartHeight;
            int sourceWidth;
            int sourceHeight;

            Rectangle destrect = new Rectangle(0, 0, x, y);
            //Locate the starting and Length of coordinate
            sourceStartWidth = sourceImg.Width / totalSlice * (sliceIndex - 1);
            sourceStartHeight = 0;
            sourceWidth = sourceImg.Width / totalSlice;
            sourceHeight = sourceImg.Height;

            Rectangle srcrect = new Rectangle(sourceStartWidth, sourceStartHeight, sourceWidth, sourceHeight);

            Image sliceImage = new Bitmap(x, y, sourceImg.PixelFormat);
            oGraphic = Graphics.FromImage(sliceImage);
            oGraphic.DrawImage(sourceImg, destrect, srcrect, GraphicsUnit.Pixel);

            sourceImg.Dispose();
            oGraphic.Dispose();

            return sliceImage;
        }

        /// <summary>
        /// overload function for DivideImage function 
        /// </summary>
        /// <param name="totalSlice"></param>
        /// <param name="sliceIndex"></param>
        /// <param name="sourceImg"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="fileName"></param>
        public void DivideImage(int totalSlice, int sliceIndex, Image sourceImg, int x, int y, string fileName)
        {
            int sourceStartWidth;
            int sourceStartHeight;
            int sourceWidth;
            int sourceHeight;
            Graphics oGraphic;

            Rectangle destrect = new Rectangle(0, 0, x, y);
            //Locate the starting and Length of coordinate
            sourceStartWidth = sourceImg.Width / totalSlice * (sliceIndex - 1);
            sourceStartHeight = 0;
            sourceWidth = sourceImg.Width / totalSlice;
            sourceHeight = sourceImg.Height;

            Rectangle srcrect = new Rectangle(sourceStartWidth, sourceStartHeight, sourceWidth, sourceHeight);

            Image sliceImage = new Bitmap(x, y, sourceImg.PixelFormat);
            oGraphic = Graphics.FromImage(sliceImage);
            oGraphic.CompositingQuality = CompositingQuality.HighQuality;
            oGraphic.SmoothingMode = SmoothingMode.HighQuality;
            oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
            oGraphic.DrawImage(sourceImg, destrect, srcrect, GraphicsUnit.Pixel);


            sliceImage.Dispose();
            oGraphic.Dispose();
        }

        /// <summary>
        /// Divide the Image based on the given pararmeter
        /// </summary>
        /// <param name="totalSlice">number of total slices</param>
        /// <param name="sourceImg">oringial image source</param>
        /// <param name="x">Frame width</param>
        /// <param name="y">Frame height</param>
        /// <param name="sliceIndex">The index arrary</param>
        /// <param name="filePath">The saving Path against the given index arrary</param>
        /// <param name="trace">Error Tracking</param>
        public void DivideImage(int totalSlice, Image sourceImg, int x, int y, int[] sliceIndex, string[] filePath, disPlayError trace )
        {
            int sourceStartWidth =0;
            int sourceStartHeight =0;
            int sourceWidth = 0;
            int sourceHeight= 0;
            string errMsg = "";
            Graphics oGraphic;

            Rectangle destrect = new Rectangle(0, 0, x, y);
            //Locate the starting and Length of coordinate
            try
            {
                //sourceStartHeight = 0;
                sourceWidth = sourceImg.Width / totalSlice;
                sourceHeight = sourceImg.Height;
            }
            catch (Exception err)
            {
                errMsg = "Image Object had been destroy" + err;
                trace(errMsg);
            }

            //Create the blank image with given size
            Image sliceImage = new Bitmap(x, y, sourceImg.PixelFormat);
            
            //Create the Graphic and initialized
            oGraphic = Graphics.FromImage(sliceImage);
            oGraphic.CompositingQuality = CompositingQuality.HighQuality;
            oGraphic.SmoothingMode = SmoothingMode.HighQuality;
            oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
            //Processing each Image
            for (int i = 0; i < sliceIndex.Length; i++)
            {
                if (sliceIndex[i]!=0)
                {
                    sourceStartWidth = sourceImg.Width / totalSlice * (sliceIndex[i]-1);
                    Rectangle srcrect = new Rectangle(sourceStartWidth, sourceStartHeight, sourceWidth, sourceHeight);
                    oGraphic.DrawImage(sourceImg, destrect,srcrect, GraphicsUnit.Pixel);
                    try
                    {
                        sliceImage.Save(filePath[i], ImageFormat.Jpeg);
                    }
                    catch(Exception err)
                    {
                        errMsg = " Problem with saving File !! Check HardDisk Storage and Contact Developer \n" + err;
                        trace(errMsg);
                    }
                }
            }
            sliceImage.Dispose();
            oGraphic.Dispose();
        }

        /// <summary>
        /// Image processing customaize for Mitsu Display
        /// </summary>
        /// <param name="fileNextFrame"></param>
        /// <param name="sameSize"></param>
        /// <param name="sourceImg"></param>
        /// <param name="filePath"></param>
        /// <param name="quality"></param>
        /// <param name="Left_STW"></param>
        /// <param name="Left_STH"></param>
        /// <param name="Left_LW"></param>
        /// <param name="Left_LH"></param>
        /// <param name="RectWStart"></param>
        /// <param name="RectHStart"></param>
        /// <param name="RectWidth"></param>
        /// <param name="RectHight"></param>
        /// <param name="trace"></param>
        /// <param name="down"></param>
        public void MitsuResize(string fileNextFrame, bool sameSize, Image sourceImg, string filePath, int quality , int Left_STW, int Left_STH, int Left_LW, int Left_LH, int RectWStart, int RectHStart, int RectWidth, int RectHight,  disPlayError trace, downQuality down)
        {
            //m_roi = new IppiSize(1280, 720);
            m_JPEGSize = 2764800;
           // byte[] pJPEG = new byte[2764800];
            Bitmap sliceImage;
            Graphics oGraphic;

            try
            {
                if (sameSize)
                {    //SaveJpeg((Bitmap)sourceImg, filePath, pJPEG, quality, down, 300);
                    int fSize = SaveJPGWithCompressionSetting(sourceImg, filePath, (long)quality);
                    while (fSize > 300)
                    {
                        quality = quality * 99 / 100;
                        fSize = SaveJPGWithCompressionSetting(sourceImg, filePath, (long)quality);
                        down(quality);
                    }
                    if (fileNextFrame != "")
                        SaveJPGWithCompressionSetting(sourceImg, fileNextFrame, (long)quality);
                }
                else
                {
                    Rectangle destrect = new Rectangle(RectWStart, RectHStart, RectWidth, RectHight);
                    sliceImage = new Bitmap(1280, 720, sourceImg.PixelFormat);
                    oGraphic = Graphics.FromImage(sliceImage);
                    oGraphic.CompositingQuality = CompositingQuality.HighSpeed;
                    oGraphic.SmoothingMode = SmoothingMode.HighSpeed;
                    oGraphic.InterpolationMode = InterpolationMode.High;
                    Rectangle srcrect = new Rectangle(Left_STW, Left_STH, Left_LW - 2, Left_LH - 2);
                    oGraphic.DrawImage(sourceImg, destrect, srcrect, GraphicsUnit.Pixel);

                    int fSize = SaveJPGWithCompressionSetting(sliceImage, filePath, (long)quality);

                    while (fSize > 300)
                    {
                        quality = quality * 99 / 100;
                        fSize = SaveJPGWithCompressionSetting(sliceImage, filePath, (long)quality);
                        down(quality);
                    }
                    if (fileNextFrame != "")
                        SaveJPGWithCompressionSetting(sliceImage, fileNextFrame, (long)quality);

                    //SaveJpeg(sliceImage, filePath, pJPEG, quality, down, 300);
                    sliceImage.Dispose();
                    oGraphic.Dispose();
                }
            }
            catch (Exception err)
            {
                string errMsg = "Problem with Saving File for Mitsu, Check HardDisk Storage and Contact Developer \n" + err;
                if (!errorOccurred)
                {
                    errorOccurred = true;
                    trace(errMsg);
                }
            }
        }

        /// <summary>
        /// Image Divided for both Ribbons
        /// </summary>
        /// <param name="sourceImg"></param>
        /// <param name="left_STW"></param>
        /// <param name="left_STH"></param>
        /// <param name="left_LW"></param>
        /// <param name="left_LH"></param>
        /// <param name="right_STW"></param>
        /// <param name="right_STH"></param>
        /// <param name="right_LW"></param>
        /// <param name="right_LH"></param>
        /// <param name="sliceIndex"></param>
        /// <param name="filePath"></param>
        /// <param name="RectWStart"></param>
        /// <param name="RectHStart"></param>
        /// <param name="RectWidth"></param>
        /// <param name="RectHight"></param>
        /// <param name="quality"></param>
        /// <param name="trace"></param>
        /// <param name="down"></param>
        public void RibbonDivide(Image sourceImg, int left_STW, int left_STH, int left_LW, int left_LH, int right_STW, int right_STH, int right_LW, int right_LH, int[] sliceIndex, string[] filePath, int RectWStart, int RectHStart, int RectWidth, int RectHight, int quality, disPlayError trace, downQuality down)
        {
            Rectangle destrect;
            Rectangle srcrect;
            
            try
            {

                if (sliceIndex[0] != 0)
                {
                    destrect = new Rectangle(RectWStart, RectHStart, RectWidth , RectHight);
                    Bitmap sliceImage = new Bitmap(2048, 1080, sourceImg.PixelFormat);
                    Graphics oGraphic = Graphics.FromImage(sliceImage);
                    oGraphic.CompositingQuality = CompositingQuality.HighSpeed;
                    oGraphic.SmoothingMode = SmoothingMode.HighSpeed;
                    oGraphic.InterpolationMode = InterpolationMode.High;
                    srcrect = new Rectangle(left_STW, left_STH, left_LW - 2, left_LH - 2);
                    oGraphic.DrawImage(sourceImg, destrect, srcrect, GraphicsUnit.Pixel);
                    //sliceImage.Save(filePath[0], ImageFormat.Jpeg);
                    //byte[] pJPEG = new byte[6635520];
                    //SaveJpeg(sliceImage, filePath[0], pJPEG, quality, down, 500);
                    int fSize = SaveJPGWithCompressionSetting(sliceImage, filePath[0], (long)quality);
                    while (fSize > 500)
                    {
                        quality = quality * 99 / 100;
                        fSize = SaveJPGWithCompressionSetting(sliceImage, filePath[0], (long)quality);
                        down(quality);
                    }
                    sliceImage.Dispose();
                    oGraphic.Dispose();
                }

                if (sliceIndex.Length > 1)
                {
                    if (sliceIndex[1] != 0)
                    {
                        destrect = new Rectangle(0, RectHStart, 1784, RectHight);
                        Bitmap sliceImage = new Bitmap(2048, 1080, sourceImg.PixelFormat);
                        Graphics oGraphic = Graphics.FromImage(sliceImage);
                        oGraphic.CompositingQuality = CompositingQuality.HighSpeed;
                        oGraphic.SmoothingMode = SmoothingMode.HighSpeed;
                        oGraphic.InterpolationMode = InterpolationMode.High;
                        srcrect = new Rectangle(right_STW, right_STH, right_LW - 2, right_LH - 2);
                        oGraphic.DrawImage(sourceImg, destrect, srcrect, GraphicsUnit.Pixel);
                        //byte[] pJPEG = new byte[6635520];
                        //SaveJpeg(sliceImage, filePath[1], pJPEG ,quality, down, 500);
                        //sliceImage.Save(filePath[1], ImageFormat.Jpeg);
                        int fSize = SaveJPGWithCompressionSetting(sliceImage, filePath[1], (long)quality);
                        while (fSize > 500)
                        {
                            quality = quality * 99 / 100;
                            fSize = SaveJPGWithCompressionSetting(sliceImage, filePath[1], (long)quality);
                            down(quality);
                        }

                        oGraphic.Dispose();
                        sliceImage.Dispose();
                    }
                }
            }
            catch (Exception err)
            {
                string errMsg = "Problem with Saving File for Ribbons, Check HardDisk Storage and Contact Developer\n" + err;
                if (!errorOccurred)
                {
                    errorOccurred = true;
                    trace(errMsg);
                }
            }
        }

        /// <summary>
        /// The Image Resize function for Ticker
        /// </summary>
        /// <param name="sourceImg"></param>
        /// <param name="Rect_Hight"></param>
        /// <param name="sliceIndex"></param>
        /// <param name="filePath"></param>
        /// <param name="quality"></param>
        /// <param name="trace"></param>
        /// <param name="down"></param>
        public void TickerResize(Image sourceImg, int Rect_Hight, int[] sliceIndex, string[] filePath, int quality, disPlayError trace, downQuality down)
        {
            Bitmap sliceImage;
            Rectangle destrect;
            Rectangle srcrect;
            Graphics oGraphic;
            try
            {
                if (sliceIndex[0] != 0)
                {
                    destrect = new Rectangle(0, 0, 2048, Rect_Hight);
                    sliceImage = new Bitmap(2048, 1080, sourceImg.PixelFormat);
                    oGraphic = Graphics.FromImage(sliceImage);
                    oGraphic.CompositingQuality = CompositingQuality.HighSpeed;
                    oGraphic.SmoothingMode = SmoothingMode.HighSpeed;
                    oGraphic.InterpolationMode = InterpolationMode.High;
                    srcrect = new Rectangle(0, 0, sourceImg.Width - 2, sourceImg.Height - 2);
                    oGraphic.DrawImage(sourceImg, destrect, srcrect, GraphicsUnit.Pixel);
                    //sliceImage.Save(filePath[0], ImageFormat.Jpeg);
                    //byte[] pJPEG = new byte[6635520];
                    //SaveJpeg(sliceImage, filePath[0], pJPEG, quality, down, 500);
                    int fSize = SaveJPGWithCompressionSetting(sliceImage, filePath[0], (long)quality);

                    while (fSize > 500)
                    {
                        quality = quality * 99 / 100;
                        fSize = SaveJPGWithCompressionSetting(sliceImage, filePath[0], (long)quality);
                        down(quality);
                    }
                    sliceImage.Dispose();
                    oGraphic.Dispose();
                }
            }
            catch (Exception err)
            {
                string errMsg = "Problem with Saving File for Ticker, Check HardDisk Storage !\n" + err;
                if (!errorOccurred)
                {
                    errorOccurred = true;
                    trace(errMsg);
                }
            }
        }

        /// <summary>
        /// Using Microsoft Image Encoder to decode and encode JPEG
        /// </summary>
        public void EncoderInit()
        {
            int j;
            ImageCodecInfo[] encoders;
            encoders = ImageCodecInfo.GetImageEncoders();
            for (j = 0; j < encoders.Length; ++j)
            {
                if (encoders[j].MimeType == "image/jpeg")
                    ici = encoders[j];
            }
        }

        /// <summary>
        /// Saving JPEG using Decoder
        /// </summary>
        /// <param name="image"></param>
        /// <param name="szFileName"></param>
        /// <param name="lCompression"></param>
        /// <returns></returns>
        private int SaveJPGWithCompressionSetting(Image image, string szFileName, long lCompression)
        {
            EncoderParameters eps = new EncoderParameters(1);
            eps.Param[0] = new EncoderParameter(Encoder.Quality, lCompression);
            //ImageCodecInfo ici = GetEncoderInfo("image/jpeg");
            image.Save(szFileName, ici, eps);
            FileInfo fInfo = new FileInfo(szFileName);
            return (int)(fInfo.Length / (long)1024);
        }

        /// <summary>
        /// Jpeg saving function using Intel Liabrary 
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="fileName"></param>
        /// <param name="pJPEG"></param>
        /// <param name="quality"></param>
        /// <param name="down"></param>
        /// <param name="limit"></param>
     /*   unsafe public void SaveJpeg(Bitmap bmp, string fileName, byte[] pJPEG, int quality,  downQuality down, int limit)
        {
            JERRCODE jerr;
            JPEGEncoder encoder = new JPEGEncoder();

            BitmapData dstData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            encoder.SetSource((byte*)dstData.Scan0, dstData.Stride, m_roi, 3, m_in_color);
            encoder.SetDestination(ref pJPEG, m_JPEGSize, quality , m_sampling, m_out_color, JMODE.JPEG_BASELINE, 0);
            int jsize = m_JPEGSize;

            jerr = encoder.WriteImageBaseline(ref jsize);
            
            if (JERRCODE.JPEG_OK == jerr)
            {
                FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
                BinaryWriter bw = new BinaryWriter(fs);
                bw.Write(pJPEG, 0, jsize);

                bw.Close();
                fs.Close();
                bmp.UnlockBits(dstData);
                bmp.Dispose();

                if ((jsize / 1024) > limit)
                    down(quality * 9 / 10);
            }
            pJPEG = null;
        }
        */
    }
}
